2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_GeneratedCode.h"
30 //==============================================================================
31 GeneratedCode::GeneratedCode (const JucerDocument
* const document_
)
32 : document (document_
),
37 GeneratedCode::~GeneratedCode()
41 int GeneratedCode::getUniqueSuffix()
46 //==============================================================================
47 String
& GeneratedCode::getCallbackCode (const String
& requiredParentClass
,
48 const String
& returnType
,
49 const String
& prototype
,
50 const bool hasPrePostUserSections
)
52 String
parentClass (requiredParentClass
);
53 if (parentClass
.isNotEmpty()
54 && ! (parentClass
.startsWith ("public ")
55 || parentClass
.startsWith ("private ")
56 || parentClass
.startsWith ("protected ")))
58 parentClass
= "public " + parentClass
;
61 for (int i
= callbacks
.size(); --i
>= 0;)
63 CallbackMethod
* const cm
= callbacks
.getUnchecked(i
);
65 if (cm
->requiredParentClass
== parentClass
66 && cm
->returnType
== returnType
67 && cm
->prototype
== prototype
)
71 CallbackMethod
* const cm
= new CallbackMethod();
74 cm
->requiredParentClass
= parentClass
;
75 cm
->returnType
= returnType
;
76 cm
->prototype
= prototype
;
77 cm
->hasPrePostUserSections
= hasPrePostUserSections
;
81 void GeneratedCode::removeCallback (const String
& returnType
, const String
& prototype
)
83 for (int i
= callbacks
.size(); --i
>= 0;)
85 CallbackMethod
* const cm
= callbacks
.getUnchecked(i
);
87 if (cm
->returnType
== returnType
&& cm
->prototype
== prototype
)
92 void GeneratedCode::addImageResourceLoader (const String
& imageMemberName
, const String
& resourceName
)
94 const String
initialiser (imageMemberName
+ " (0)");
96 if (! initialisers
.contains (initialiser
, false))
98 initialisers
.add (initialiser
);
100 privateMemberDeclarations
101 << "Image " << imageMemberName
<< ";\n";
103 if (resourceName
.isNotEmpty())
106 << imageMemberName
<< " = ImageCache::getFromMemory ("
107 << resourceName
<< ", " << resourceName
<< "Size);\n";
112 const StringArray
GeneratedCode::getExtraParentClasses() const
116 for (int i
= 0; i
< callbacks
.size(); ++i
)
118 CallbackMethod
* const cm
= callbacks
.getUnchecked(i
);
119 s
.add (cm
->requiredParentClass
);
125 const String
GeneratedCode::getCallbackDeclarations() const
129 for (int i
= 0; i
< callbacks
.size(); ++i
)
131 CallbackMethod
* const cm
= callbacks
.getUnchecked(i
);
133 s
<< cm
->returnType
<< " " << cm
->prototype
<< ";\n";
139 const String
GeneratedCode::getCallbackDefinitions() const
143 for (int i
= 0; i
< callbacks
.size(); ++i
)
145 CallbackMethod
* const cm
= callbacks
.getUnchecked(i
);
147 const String
userCodeBlockName ("User"
148 + makeValidCppIdentifier (cm
->prototype
.upToFirstOccurrenceOf ("(", false, false),
149 true, true, false).trim());
151 if (userCodeBlockName
.isNotEmpty() && cm
->hasPrePostUserSections
)
153 s
<< cm
->returnType
<< " " << className
<< "::" << cm
->prototype
154 << "\n{\n //[" << userCodeBlockName
<< "_Pre]\n //[/" << userCodeBlockName
156 << indentCode (cm
->content
.trim(), 4)
157 << "\n\n //[" << userCodeBlockName
<< "_Post]\n //[/" << userCodeBlockName
162 s
<< cm
->returnType
<< " " << className
<< "::" << cm
->prototype
164 << indentCode (cm
->content
.trim(), 4)
172 //==============================================================================
173 const String
GeneratedCode::getClassDeclaration() const
175 StringArray parentClassLines
;
176 parentClassLines
.addTokens (parentClasses
, ",", String::empty
);
177 parentClassLines
.addArray (getExtraParentClasses());
179 parentClassLines
.trim();
180 parentClassLines
.removeEmptyStrings();
181 parentClassLines
.removeDuplicates (false);
183 if (parentClassLines
.contains ("public Button", false))
184 parentClassLines
.removeString ("public Component", false);
187 r
<< className
<< " : ";
189 r
+= parentClassLines
.joinIntoString (",\n" + String::repeatedString (" ", r
.length()));
194 const String
GeneratedCode::getInitialiserList() const
196 StringArray
inits (initialisers
);
198 if (parentClassInitialiser
.isNotEmpty())
199 inits
.insert (0, parentClassInitialiser
);
202 inits
.removeEmptyStrings();
203 inits
.removeDuplicates (false);
207 if (inits
.size() == 0)
212 for (int i
= 0; i
< inits
.size(); ++i
)
214 String
init (inits
[i
]);
216 while (init
.endsWithChar (','))
217 init
= init
.dropLastCharacters (1);
221 if (i
< inits
.size() - 1)
230 static const String
getIncludeFileCode (StringArray files
)
233 files
.removeEmptyStrings();
234 files
.removeDuplicates (false);
238 for (int i
= 0; i
< files
.size(); ++i
)
239 s
<< "#include \"" << files
[i
] << "\"\n";
244 //==============================================================================
245 static void replaceTemplate (String
& text
, const String
& itemName
, const String
& value
)
249 const int index
= text
.indexOf ("%%" + itemName
+ "%%");
256 for (int i
= index
; --i
>= 0;)
264 text
= text
.replaceSection (index
, itemName
.length() + 4,
265 indentCode (value
, indentLevel
));
269 //==============================================================================
270 static bool getUserSection (const StringArray
& lines
, const String
& tag
, StringArray
& resultLines
)
272 const int start
= indexOfLineStartingWith (lines
, "//[" + tag
+ "]", 0);
277 const int end
= indexOfLineStartingWith (lines
, "//[/" + tag
+ "]", start
+ 1);
279 for (int i
= start
+ 1; i
< end
; ++i
)
280 resultLines
.add (lines
[i
]);
285 static void copyAcrossUserSections (String
& dest
, const String
& src
)
287 StringArray srcLines
, dstLines
;
288 srcLines
.addLines (src
);
289 dstLines
.addLines (dest
);
291 for (int i
= 0; i
< dstLines
.size(); ++i
)
293 if (dstLines
[i
].trimStart().startsWith ("//["))
295 String
tag (dstLines
[i
].trimStart().substring (3));
296 tag
= tag
.upToFirstOccurrenceOf ("]", false, false);
298 jassert (! tag
.startsWithChar ('/'));
300 if (! tag
.startsWithChar ('/'))
302 const int endLine
= indexOfLineStartingWith (dstLines
,
308 StringArray sourceLines
;
310 if (getUserSection (srcLines
, tag
, sourceLines
))
313 for (j
= endLine
- i
; --j
> 0;)
314 dstLines
.remove (i
+ 1);
316 for (j
= 0; j
< sourceLines
.size(); ++j
)
317 dstLines
.insert (++i
, sourceLines
[j
].trimEnd());
329 dstLines
.set (i
, dstLines
[i
].trimEnd());
332 dest
= dstLines
.joinIntoString ("\n") + "\n";
335 //==============================================================================
336 void GeneratedCode::applyToCode (String
& code
,
337 const String
& fileNameRoot
,
338 const bool isForPreview
,
339 const String
& oldFileWithUserData
) const
342 String
headerGuard ("__JUCER_HEADER_");
343 headerGuard
<< className
.toUpperCase().retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
344 << "_" << fileNameRoot
.toUpperCase().retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
345 << "_" << String::toHexString (Random::getSystemRandom().nextInt()).toUpperCase()
347 replaceTemplate (code
, "headerGuard", headerGuard
);
349 replaceTemplate (code
, "creationTime", Time::getCurrentTime().toString (true, true, true));
351 replaceTemplate (code
, "className", className
);
352 replaceTemplate (code
, "constructorParams", constructorParams
);
353 replaceTemplate (code
, "initialisers", getInitialiserList());
355 replaceTemplate (code
, "classDeclaration", getClassDeclaration());
356 replaceTemplate (code
, "privateMemberDeclarations", privateMemberDeclarations
);
357 replaceTemplate (code
, "publicMemberDeclarations", getCallbackDeclarations() + "\n" + publicMemberDeclarations
);
359 replaceTemplate (code
, "methodDefinitions", getCallbackDefinitions());
361 replaceTemplate (code
, "includeFilesH", getIncludeFileCode (includeFilesH
));
362 replaceTemplate (code
, "includeFilesCPP", getIncludeFileCode (includeFilesCPP
));
364 replaceTemplate (code
, "constructor", constructorCode
);
365 replaceTemplate (code
, "destructor", destructorCode
);
369 replaceTemplate (code
, "metadata", jucerMetadata
);
370 replaceTemplate (code
, "staticMemberDefinitions", staticMemberDefinitions
);
374 replaceTemplate (code
, "metadata", " << Metadata isn't shown in the code preview >>\n");
375 replaceTemplate (code
, "staticMemberDefinitions", "// Static member declarations and resources would go here... (these aren't shown in the code preview)");
378 copyAcrossUserSections (code
, oldFileWithUserData
);